////
/// @group dialog
////

@use "sass:map";
@use "../utils";
@use "../spacing";
@use "../box-shadows";
@use "../box/box";
@use "../transition/transition";
@use "../interaction/interaction";
@use "../theme/theme";

/// Set to `true` to disable all the styles
/// @type Boolean
$disable-everything: false !default;

/// Set to `true` of the default dialog enter/exit transition styles should not
/// be generated.
///
/// @type Boolean
$disable-default-transition: false !default;

/// Set to `true` when the `FixedDialog` will not be used.
///
/// @type Boolean
$disable-fixed: false !default;

/// Set to `true` if the `DialogHeader` will not be used.
///
/// @type Boolean
$disable-header: false !default;

/// Set to `true` if the `DialogTitle` will not be used.
///
/// @type Boolean
$disable-title: false !default;

/// Set to `true` if the `DialogContent` will not be used.
///
/// @type Boolean
$disable-content: false !default;

/// Set to `true` if the `DialogFooter` will not be used.
///
/// @type Boolean
$disable-footer: false !default;

/// Set to `true` if the `Dialog` component will never gain focus because each
/// `Dialog` usage has a child component with `defaultFocus` enabled.
///
/// @type Boolean
$disable-focus-outline: false !default;

/// Set to `true` if the `DialogFooter` will never set `align="stacked-start"`
/// and `align="stacked-end"`
///
/// @type Boolean
$disable-footer-flex-vertical: false !default;

/// Set to `true` if the `DialogFooter` will never set `align="start"` and
/// `align="stacked-start"`.
///
/// @type Boolean
$disable-footer-flex-start: false !default;

/// Set to `true` if the `DialogFooter` will never set `align="between"`.
///
/// @type Boolean
$disable-footer-space-between: false !default;

/// Set to `true` if the `DialogFooter` will never set `align="end"` and
/// `align="stacked-end".
///
/// @type Boolean
$disable-footer-flex-end: false !default;

/// A number between 0-24 representing the box-shadow elevation for the dialog.
///
/// @type Number
$elevation: 16 !default;

/// The z-index to apply to the `Dialog`.
///
/// @type Number
$z-index: utils.$temporary-element-z-index !default;

/// The default background color for a dialog.
/// @type Color
$background-color: if(
  theme.$disable-dark-elevation,
  theme.theme-get-var(surface-color),
  null
) !default;

/// The default text color for a dialog.
/// @type Color
$color: if(
  theme.$disable-dark-elevation,
  theme.theme-get-var(text-primary-color),
  null
) !default;

/// The `min-width` to apply to all `Dialog`s.
///
/// @type Number
$min-width: 17.5rem !default;

/// The `width` to use when `width="small"`.
///
/// @type Number
$small-width: 25rem !default;

/// The `width` to use when `width="medium"`.
///
/// @type Number
$medium-width: 40rem !default;

/// The `width` to use when `width="large"`.
///
/// @type Number
$large-width: 60rem !default;

/// The `width` to use when `width="extra-large"`.
///
/// @type Number
$extra-large-width: 80rem !default;

/// The amount of spacing to apply to the left and right of the dialog when it
/// is centered.
///
/// @type Number
$horizontal-margin: calc(spacing.get-var(lg) * 1.25) !default;

/// The amount of spacing to apply to the top and bottom of the dialog when it
/// is centered.
///
/// @type Number
$vertical-margin: spacing.get-var(lg) !default;

/// The distance to move while the dialog enters and exits.
/// @type Number
$transition-distance: 1.875rem !default;

/// The `Dialog` enter transition duration. If this value changes, the
/// `Dialog.timeout` should be updated as well.
///
/// @type Number
$enter-duration: transition.$enter-duration !default;

/// The `Dialog` enter transition timing function.
///
/// @type Number
$enter-timing-function: transition.$deceleration-timing-function !default;

/// If this value changes, the `Dialog.timeout` should be updated as well.
///
/// @type Number
$leave-timing-function: transition.$acceleration-timing-function !default;

/// The `Dialog` exit transition timing function.
///
/// @type Number
$leave-duration: transition.$leave-duration !default;

/// The amount of padding to apply to the `DialogHeader` component.
///
/// @type Number
$header-padding: spacing.get-var(lg) !default;

/// The amount of padding-bottom to apply to the `DialogHeader` component.
///
/// @type Number
$header-padding-bottom: calc(spacing.get-var(md) * 1.25) !default;

/// The amount of padding-bottom to apply to the `DialogContent` component.
///
/// @type Number
$content-padding: spacing.get-var(lg) !default;

/// The amount of padding-bottom to apply to the `DialogFooter` component.
///
/// @type Number
$footer-padding: spacing.get-var(sm) !default;

/// The available configurable css variables and mostly used internally for the
/// `get-var`, `set-var`, and `use-var` utils.
/// @type List
$variables: (
  min-width,
  horizontal-margin,
  vertical-margin,
  z-index,
  header-padding,
  header-padding-bottom,
  content-padding,
  footer-padding,
  width,
  small-width,
  medium-width,
  large-width,
  extra-large-width
);

/// @param {String} name - The supported variable name
/// @param {any} fallback [null] - An optional fallback value
/// @returns {String} a `var()` statement
@function get-var($name, $fallback: null) {
  $var: utils.get-var-name($variables, $name, "dialog");

  @if $fallback {
    @return var(#{$var}, #{$fallback});
  }

  @return var(#{$var});
}

/// @param {String} name - The supported variable name
/// @param {any} value - The value to set the variable to. Supports `null` which
/// will just be a no-op.
@mixin set-var($name, $value) {
  @if $value {
    #{utils.get-var-name($variables, $name, "dialog")}: #{$value};
  }
}

/// @param {String} property - The css property to apply the variable to
/// @param {String} name [$property] - The supported variable name
/// @param {any} fallback [null] - An optional fallback value if the variable
/// has not been set
@mixin use-var($property, $name: $property, $fallback: null) {
  #{$property}: get-var($name, $fallback);
}

/// Conditionally applies the css variables based on feature flags
@mixin variables {
  @if not $disable-everything {
    @include set-var(min-width, $min-width);
    @include set-var(horizontal-margin, $horizontal-margin);
    @include set-var(vertical-margin, $vertical-margin);
    @include set-var(z-index, $z-index);

    @if $small-width {
      @include set-var(small-width, $small-width);
    }
    @if $medium-width {
      @include set-var(medium-width, $medium-width);
    }
    @if $large-width {
      @include set-var(large-width, $large-width);
    }
    @if $extra-large-width {
      @include set-var(extra-large-width, $extra-large-width);
    }

    @if not $disable-header {
      @include set-var(header-padding, $header-padding);
      @include set-var(header-padding-bottom, $header-padding-bottom);
    }

    @if not $disable-content {
      @include set-var(content-padding, $content-padding);
    }
    @if not $disable-footer {
      @include set-var(footer-padding, $footer-padding);
    }
  }
}

/// Generates all the styles based on feature flags.
///
/// @param {Boolean} disable-layer [false] - Set this to `true` to disable the
/// layer behavior
@mixin styles($disable-layer: false) {
  @if not $disable-everything {
    @include utils.optional-layer(dialog, $disable-layer) {
      .rmd-dialog-container {
        &--centered {
          @include use-var(z-index);

          align-items: center;
          display: flex;
          inset: 0;
          justify-content: center;
          margin: get-var(vertical-margin) get-var(horizontal-margin);
          margin-right: calc(
            #{get-var(horizontal-margin)} + #{utils.scrollbar-size()}
          );

          // pointer-events are disabled so the overlay can be clicked instead
          pointer-events: none;
          position: fixed;
        }
      }

      .rmd-dialog {
        @include box-shadows.box-shadow($elevation);

        background-color: $background-color;
        color: $color;
        display: flex;
        flex-direction: column;
        max-height: 100%;
        max-width: 100%;
        outline: none;
        pointer-events: auto;

        &--centered {
          @include use-var(min-width);
          @include use-var(width);
        }

        @if $small-width {
          &--s-width {
            @include set-var(width, get-var(small-width));
          }
        }

        @if $medium-width {
          &--m-width {
            @include set-var(width, get-var(medium-width));
          }
        }

        @if $large-width {
          &--l-width {
            @include set-var(width, get-var(large-width));
          }
        }

        @if $extra-large-width {
          &--xl-width {
            @include set-var(width, get-var(extra-large-width));
          }
        }

        &--full-page {
          @include use-var(z-index);

          height: 100%;
          inset: 0;
          overflow: auto;
          position: fixed;
          width: 100%;
        }

        &--no-box-shadow {
          box-shadow: none;
        }

        @if not $disable-focus-outline {
          // Note: Do not use the `interaction-outline` mixin +
          // `interaction.set-var(interaction.$focus-color)` like normal focus
          // elements since it'll make all focusable children update with the
          // outline color as well
          @if utils.$disable-focus-visible {
            @include utils.keyboard-only {
              &--outline:focus {
                outline: interaction.get-var(focus-color) solid
                  interaction.get-var(focus-width);
              }
            }
          } @else {
            &--outline:focus-visible {
              outline: interaction.get-var(focus-color)
                solid
                interaction.get-var(focus-width);
            }
          }
        }

        @if not $disable-default-transition {
          &--enter {
            transform: translateY($transition-distance);
          }

          &--enter-active {
            transform: translateY(0);
            transition: transform $enter-duration;
            transition-timing-function: $enter-timing-function;
          }

          &--exit {
            opacity: 1;
            transform: translateY(0);
            transition:
              transform $leave-duration,
              opacity $leave-duration;
            transition-timing-function: $leave-timing-function;
          }

          &--exit-active {
            opacity: 0;
            transform: translateY($transition-distance);
          }
        }

        @if not $disable-fixed {
          &--fixed {
            @include use-var(z-index);
          }
        }

        @if not $disable-header {
          &__header {
            @include box.set-var(padding, get-var(header-padding));
            @include use-var(padding-bottom, header-padding-bottom);

            flex: 0 0 auto;
          }
        }

        @if not $disable-title {
          &__title {
            // this makes it so it's easy to add a close button after the title
            flex: 1 1 auto;
          }
        }

        @if not $disable-content {
          &__content {
            flex: 1 1 auto;
            overflow: auto;

            &--padded {
              @include use-var(padding, content-padding);
            }
          }
        }

        @if not $disable-footer {
          &__footer {
            @include use-var(padding, footer-padding);

            flex: 0 0 auto;

            @if not
              $disable-footer-flex-vertical or not
              $disable-footer-flex-start or not
              $disable-footer-space-between or not
              $disable-footer-flex-end
            {
              &--flex {
                display: flex;
              }
            }

            @if not $disable-footer-flex-vertical {
              &--flex-v {
                flex-direction: column;
              }
            }

            @if not $disable-footer-flex-start {
              &--start {
                justify-content: flex-start;
              }
            }

            @if not $disable-footer-space-between {
              &--between {
                justify-content: space-between;
              }
            }

            @if not $disable-footer-flex-end {
              &--end {
                justify-content: flex-end;
              }
            }
          }
        }
      }
    }
  }
}
